﻿# coding: utf-8

import wx
import wx.lib.agw.flatmenu as FM
from wx.lib.agw.artmanager import ArtManager, RendererBase, DCSaver
from wx.lib.agw.fmresources import ControlFocus, ControlPressed
from wx.lib.agw.fmresources import FM_OPT_SHOW_CUSTOMIZE, FM_OPT_SHOW_TOOLBAR, FM_OPT_MINIBAR
import wx.lib.agw.aui as aui
from wx.lib.wordwrap import wordwrap

import Panel
import Dialog

class wxMainFrame(wx.Frame):
		
	__ID_PANEL_EDITOR_SCENE = wx.NewId()
	__ID_PANEL_TERRAIN_HEIGHT = wx.NewId()
	__ID_PANEL_TERRAIN_LAYER = wx.NewId()
	__ID_PANEL_PARTICLE_SYSTEM = wx.NewId()
	__ID_PANEL_ASSETS = wx.NewId()
	__ID_PANEL_HIERARCHY = wx.NewId()
	__ID_PANEL_PROPERTY = wx.NewId()
	__ID_PANEL_PYTHON_SHELL = wx.NewId()
	__ID_PANEL_LOGIC_GRID = wx.NewId()
	
	__PANEL_CREATE_LIST = [
		{'name' : 'PANEL_EDITOR_SCENE', 'id' : __ID_PANEL_EDITOR_SCENE, 'class' : wx.Panel, 'title' : TD.PANEL_EDITOR_SCENE, 'icon' : IL.ID_IMAGE_EDITOR_SCENE},
		{'name' : 'PANEL_TERRAIN_HEIGHT', 'id' : __ID_PANEL_TERRAIN_HEIGHT, 'class' : Panel.wxPanelTerrainHeight, 'title' : TD.PANEL_TERRAIN_HEIGHT, 'icon' : IL.ID_IMAGE_TERRAIN_HEIGHT},
		{'name' : 'PANEL_TERRAIN_LAYER', 'id' : __ID_PANEL_TERRAIN_LAYER, 'class' : Panel.wxPanelTerrainLayer, 'title' : TD.PANEL_TERRAIN_LAYER, 'icon' : IL.ID_IMAGE_TERRAIN_LAYER},
		{'name' : 'PANEL_PARTICLE_SYSTEM', 'id' : __ID_PANEL_PARTICLE_SYSTEM, 'class' : Panel.wxPanelParticleSystem, 'title' : TD.PANEL_PARTICLE_SYSTEM, 'icon' : IL.ID_IMAGE_PARTICLE_SYSTEM},
		{'name' : 'PANEL_ASSETS', 'id' : __ID_PANEL_ASSETS, 'class' : Panel.wxPanelAssets, 'title' : TD.PANEL_ASSETS, 'icon' : IL.ID_IMAGE_ASSETS},
		{'name' : 'PANEL_HIERARCHY', 'id' : __ID_PANEL_HIERARCHY, 'class' : Panel.wxPanelHierarchy, 'title' : TD.PANEL_HIERARCHY, 'icon' : IL.ID_IMAGE_HIERARCHY},
		{'name' : 'PANEL_PROPERTY', 'id' : __ID_PANEL_PROPERTY, 'class' : Panel.wxPanelProperty, 'title' : TD.PANEL_PROPERTY, 'icon' : IL.ID_IMAGE_PROPERTY},
		{'name' : 'PANEL_LOGIC_GRID', 'id' : __ID_PANEL_LOGIC_GRID, 'class' : Panel.wxPanelLogicGrid, 'title' : TD.PANEL_LOGIC_GRID, 'icon' : IL.ID_IMAGE_LOGIC_GRID},
		{'name' : 'PANEL_PYTHON_SHELL', 'id' : __ID_PANEL_PYTHON_SHELL, 'class' : Panel.wxPanelPythonShell, 'title' : TD.PANEL_PYTHON_SHELL, 'icon' : IL.ID_IMAGE_PYTHON_SHELL},
	]
	
	__PANEL_MENU_CREATE_LIST = [
		{'id' : __ID_PANEL_EDITOR_SCENE, 'title' : TD.MENU_VIEW_EDITOR_SCENE, 'icon' : IL.ID_IMAGE_EDITOR_SCENE},
		{'id' : None, 'title' : TD.MENU_VIEW_TERRAIN, 'child' : [
			{'id' : __ID_PANEL_TERRAIN_HEIGHT, 'title' : TD.MENU_VIEW_TERRAIN_HEIGHT, 'icon' : IL.ID_IMAGE_TERRAIN_HEIGHT},
			{'id' : __ID_PANEL_TERRAIN_LAYER, 'title' : TD.MENU_VIEW_TERRAIN_LAYER, 'icon' : IL.ID_IMAGE_TERRAIN_LAYER},
			]
		},
		{'id' : None, 'title' : TD.MENU_VIEW_EFFECT, 'child' : [
			{'id' : __ID_PANEL_PARTICLE_SYSTEM, 'title' : TD.MENU_VIEW_PARTICLE_SYSTEM, 'icon' : IL.ID_IMAGE_PARTICLE_SYSTEM},
			]
		},
		{'id' : __ID_PANEL_ASSETS, 'title' : TD.MENU_VIEW_ASSETS, 'icon' : IL.ID_IMAGE_ASSETS},
		{'id' : __ID_PANEL_HIERARCHY, 'title' : TD.MENU_VIEW_HIERARCHY, 'icon' : IL.ID_IMAGE_HIERARCHY},
		{'id' : __ID_PANEL_PROPERTY, 'title' : TD.MENU_VIEW_PROPERTY, 'icon' : IL.ID_IMAGE_PROPERTY},
		{'id' : None, 'title' : TD.MENU_VIEW_LOGIC, 'child' : [
			{'id' : __ID_PANEL_LOGIC_GRID, 'title' : TD.MENU_VIEW_LOGIC_GRID, 'icon' : IL.ID_IMAGE_LOGIC_GRID},
			]
		},
		{'id' : __ID_PANEL_PYTHON_SHELL, 'title' : TD.MENU_VIEW_PYTHON_SHELL, 'icon' : IL.ID_IMAGE_PYTHON_SHELL},
	]
	
	
	__TOOL_BAR_OP_CREATE_LIST = [
		{'id' : OPD.OP_SELECT,          'title' : TD.OP_SELECT,         'icon' : IL.ID_IMAGE_SELECT},
		{'id' : OPD.OP_TRANSLATION,     'title' : TD.OP_TRANSLATION,    'icon' : IL.ID_IMAGE_TRANSLATION},
		{'id' : OPD.OP_ROTATION,        'title' : TD.OP_ROTATION,       'icon' : IL.ID_IMAGE_ROTATION},
		{'id' : OPD.OP_SCALING,         'title' : TD.OP_SCALING,        'icon' : IL.ID_IMAGE_SCALING},
		{'id' : OPD.OP_BUILD_SINGLE,    'title' : TD.OP_BUILD_SINGLE,   'icon' : IL.ID_IMAGE_BUILD_SINGLE},
		{'id' : OPD.OP_TERRAIN_HEIGHT_PAINT, 'title' : TD.OP_TERRAIN_HEIGHT_PAINT, 'icon' : IL.ID_IMAGE_TERRAIN_HEIGHT_PAINT},
		{'id' : OPD.OP_TERRAIN_LAYER_PAINT, 'title' : TD.OP_TERRAIN_LAYER_PAINT, 'icon' : IL.ID_IMAGE_TERRAIN_LAYER_PAINT},            
	]
	
	def __init__(self):
		wx.Frame.__init__(self, None, -1, TD.APP_NAME, size = (800, 600),
			style = wx.DEFAULT_FRAME_STYLE|wx.MAXIMIZE)
	
		# Data define.
		self._panelList = {}
	
		# Set application icon.
		self.SetIcon(wx.Icon('Resource/icon/main.ico', wx.BITMAP_TYPE_ICO))
	
		# Create PyAUI system.
		self._auiManager = aui.AuiManager()
		self._auiManager.SetManagedWindow(self)
	
		# Create main menu
		self.__CreateMainMenu()
	
		# Create tool bar
		self.__CreateToolBar()
	
		# Create all views
		self.__CreateAllViews()
	
		# Bind all events
		self.__BindAllEvents()
	
		# Put all views into PyAUI system.
		self.__CombineAll()
	
	def __CreateToolBar(self):
		self.__CreateToolBarPanel()
		self.__CreateToolBarOperate()
	
	def __CreateToolBarPanel(self):
		""" Create panel tool bar """
		
		self._toolBarPanel = aui.AuiToolBar(self, wx.NewId(), style = aui.AUI_TB_DEFAULT_STYLE|aui.AUI_TB_OVERFLOW)
		self._toolBarPanel.SetToolBitmapSize(wx.Size(IL.IMAGE_SMALL, IL.IMAGE_SMALL))
		for item in wxMainFrame.__PANEL_CREATE_LIST:
			self._toolBarPanel.AddSimpleTool(item['id'], '', IL.GetBitmap(item['icon'], IL.IMAGE_SMALL), short_help_string = item['title'], kind = aui.ITEM_CHECK)
				
		self._toolBarPanel.Realize()
	
	def __CreateToolBarOperate(self):
		""" Create operate tool bar """
		
		self._toolBarOperate = aui.AuiToolBar(self, wx.NewId(), style = aui.AUI_TB_DEFAULT_STYLE|aui.AUI_TB_OVERFLOW)
		self._toolBarOperate.SetToolBitmapSize(wx.Size(IL.IMAGE_SMALL, IL.IMAGE_SMALL))
		self._toolBarOperate.AddSeparator()
		
		for op in wxMainFrame.__TOOL_BAR_OP_CREATE_LIST:
			id = op['id']
			title = op['title']
			icon = op['icon']
			bmp = IL.GetBitmap(icon, IL.IMAGE_SMALL)
			self._toolBarOperate.AddSimpleTool(id, title, bmp, title, aui.ITEM_RADIO)
			self.Bind(wx.EVT_MENU, self.__OnTBClickOperate, id = id)

		self._toolBarOperate.Realize()
		self.OnCurrentOperateChanged()
		
	def __OnTBClickOperate(self, e):
		WORLD_EDITOR.ChangeCurrentOperate(e.GetId(), False)
			
	def OnCurrentOperateChanged(self):
		""" Notify refresh tool bar """
		
		self._toolBarOperate.ToggleTool(WORLD_EDITOR.GetCurrentOperate(), aui.AUI_BUTTON_STATE_CHECKED)
		self._toolBarOperate.Refresh()
	
	def __CreateMainMenuPanel(self, menu, itemList):
		""" Create panel menu """
		
		for item in itemList:
			id = item['id']
			if id == None:
				subMenu = FM.FlatMenu()
				menu.AppendItem(FM.FlatMenuItem(menu, wx.NewId(), item['title'], subMenu = subMenu))
				self.__CreateMainMenuPanel(subMenu, item['child'])
			else:
				menu.AppendItem(FM.FlatMenuItem(menu, id, item['title'], normalBmp = IL.GetBitmap(item['icon'], IL.IMAGE_SMALL), kind = wx.ITEM_CHECK))
	
	def __CreateMainMenu(self):
		""" Create main menu """
		
		# Create menu bar.
		self._menuBar = FM.FlatMenuBar(self, wx.ID_ANY, 32, 2, options = FM_OPT_SHOW_CUSTOMIZE)
		menuFile = FM.FlatMenu()
		menuEdit = FM.FlatMenu()
		menuView = FM.FlatMenu()
		menuHelp = FM.FlatMenu()

		self._menuBar.Append(menuFile, TD.MENU_FILE)
		self._menuBar.Append(menuEdit, TD.MENU_EDIT)
		self._menuBar.Append(menuView, TD.MENU_VIEW)
		self._menuBar.Append(menuHelp, TD.MENU_HELP)

		# Create file menu
		self._idMenuFileNewScene = wx.NewId()
		self._idMenuFileLoadScene = wx.NewId()
		self._idMenuFileSaveScene = wx.NewId()
		self._idMenuFileSaveSceneAs = wx.NewId()
		self._idMenuFileGlobalSetting = wx.NewId()
		self._idMenuFileExit = wx.NewId()

		menuFile.AppendItem(FM.FlatMenuItem(menuFile, self._idMenuFileNewScene, TD.MENU_FILE_NEW_SCENE, normalBmp = IL.GetBitmap(IL.ID_IMAGE_FILE_NEW, IL.IMAGE_SMALL)))
		menuFile.AppendItem(FM.FlatMenuItem(menuFile, self._idMenuFileLoadScene, TD.MENU_FILE_LOAD_SCENE))
		menuFile.AppendItem(FM.FlatMenuItem(menuFile, self._idMenuFileSaveScene, TD.MENU_FILE_SAVE_SCENE))
		menuFile.AppendItem(FM.FlatMenuItem(menuFile, self._idMenuFileSaveSceneAs, TD.MENU_FILE_SAVE_SCENE_AS))
		menuFile.AppendSeparator()
		menuFile.AppendItem(FM.FlatMenuItem(menuFile, self._idMenuFileGlobalSetting, TD.MENU_FILE_GLOBAL_SETTING, normalBmp = IL.GetBitmap(IL.ID_IMAGE_SETTING, IL.IMAGE_SMALL)))
		menuFile.AppendSeparator()
		menuFile.AppendItem(FM.FlatMenuItem(menuFile, self._idMenuFileExit, TD.MENU_FILE_EXIT, normalBmp = IL.GetBitmap(IL.ID_IMAGE_EXIT, IL.IMAGE_SMALL)))

		# Create edit menu
		self._idMenuEditUndo = wx.NewId()
		self._idMenuEditRedo = wx.NewId()
		
		menuEdit.AppendItem(FM.FlatMenuItem(menuEdit, self._idMenuEditUndo, TD.MENU_EDIT_UNDO, normalBmp = IL.GetBitmap(IL.ID_IMAGE_UNDO, IL.IMAGE_SMALL)))
		menuEdit.AppendItem(FM.FlatMenuItem(menuEdit, self._idMenuEditRedo, TD.MENU_EDIT_REDO, normalBmp = IL.GetBitmap(IL.ID_IMAGE_REDO, IL.IMAGE_SMALL)))
		
		# Create view menu
		self.__CreateMainMenuPanel(menuView, wxMainFrame.__PANEL_MENU_CREATE_LIST)

		# Create help menu.
		self._idMenuHelpTopics = wx.NewId()
		self._idMenuHelpAbout = wx.NewId()

		menuHelp.AppendItem(FM.FlatMenuItem(menuHelp, self._idMenuHelpTopics, TD.MENU_HELP_TOPICS))
		menuHelp.AppendItem(FM.FlatMenuItem(menuHelp, self._idMenuHelpAbout, TD.MENU_HELP_ABOUT))

		self._menuBar.Refresh()
		self._menuBar.UpdateAcceleratorTable()
	
	def __CreateAllViews(self):
		""" Create all panels """
		
		self._mainNotebook = aui.AuiNotebook(self, wx.NewId(), wx.DefaultPosition, wx.DefaultSize, WS.MAIN_FRAME_NOTEBOOK_STYLE);
		self._mainNotebook.SetArtProvider(aui.ChromeTabArt())

		for item in wxMainFrame.__PANEL_CREATE_LIST:
			id = item['id']
			title = item['title']
			classType = item['class']
			panel = classType(self, id)
			panel.SetLabel(title)
			self._panelList[id] = panel
			__builtins__[item['name']] = panel

			if panel.GetLabel() in GLOBAL_SETTING._visiblePanelList:
				self.__AddPanel(panel)
			else:
				panel.Show(False)

		self._mainNotebook.Update()
	
	def __AddPanel(self, panel):
		self._mainNotebook.AddPage(panel, panel.GetLabel(), True)            
		panel.Show()
	
	def __RemovePanel(self, idx):
		page = self._mainNotebook.GetPage(idx)
		page.Hide()
		self._mainNotebook.RemovePage(idx)
		self._mainNotebook.Update()

	def __BindEventPanel(self, itemList):
		for item in itemList:
			id = item['id']
			if id == None:
				self.__BindEventPanel(item['child'])
			else:
				self.Bind(wx.EVT_MENU, self.__OnMenuClick, id = id)
				self.Bind(wx.EVT_UPDATE_UI, self.__OnMenuUpdateUI, id = id)

	def __BindAllEvents(self):
			self.Bind(wx.EVT_CLOSE, self.__OnClose)
	
			self._mainNotebook.Bind(aui.EVT_AUINOTEBOOK_PAGE_CLOSE, self.__OnPanelClose)
	
			self.__BindEventPanel(wxMainFrame.__PANEL_MENU_CREATE_LIST)
	
			PANEL_EDITOR_SCENE.Bind(wx.EVT_SIZE, self.__OnWindowResize)
			PANEL_EDITOR_SCENE.Bind(wx.EVT_RIGHT_DOWN, self.__OnMouseRightDown)
			PANEL_EDITOR_SCENE.Bind(wx.EVT_RIGHT_UP, self.__OnMouseRightUp)
			PANEL_EDITOR_SCENE.Bind(wx.EVT_MIDDLE_DOWN, self.__OnMouseMiddleDown)
			PANEL_EDITOR_SCENE.Bind(wx.EVT_MIDDLE_UP, self.__OnMouseMiddleUp)
			PANEL_EDITOR_SCENE.Bind(wx.EVT_LEFT_DOWN, self.__OnMouseLeftDown)
			PANEL_EDITOR_SCENE.Bind(wx.EVT_LEFT_UP, self.__OnMouseLeftUp)
			PANEL_EDITOR_SCENE.Bind(wx.EVT_MOTION, self.__OnMouseMotion)
			PANEL_EDITOR_SCENE.Bind(wx.EVT_MOUSEWHEEL, self.__OnMouseWheel)
			PANEL_EDITOR_SCENE.Bind(wx.EVT_KEY_DOWN, self.__OnKeyDown)
			PANEL_EDITOR_SCENE.Bind(wx.EVT_KEY_UP, self.__OnKeyUp)
			PANEL_EDITOR_SCENE.Bind(wx.EVT_MOUSE_CAPTURE_LOST, self.__OnMouseCaptureLost)
	
			# File menu event.
			self.Bind(wx.EVT_MENU, self.__OnCmdFileGlobalSetting, id = self._idMenuFileGlobalSetting)
	
			# Edit menu event.
			self.Bind(wx.EVT_MENU, self.__OnCmdEditUndo, id = self._idMenuEditUndo)
			self.Bind(wx.EVT_MENU, self.__OnCmdEditRedo, id = self._idMenuEditRedo)
			
			# Help menu event.
			self.Bind(wx.EVT_MENU, self.__OnCmdHelpAbout, id = self._idMenuHelpAbout)
			
	def __OnCmdHelpAbout(self, e):
			info = wx.AboutDialogInfo()
			
			info.SetName(TD.APP_NAME)
			info.SetVersion(TD.VERSION)
			info.SetCopyright(TD.COPYRIGHT)
			info.SetDescription(wordwrap(TD.DESCRIPTION, 350, wx.ClientDC(self)))
			info.SetWebSite((u'http://sites.google.com/site/zebbey', TD.HOME_PAGE_DESC))
			info.SetDevelopers([u'Zeb (email:zebbey@gmail.com)'])
			
			wx.AboutBox(info)        
			
	def __OnCmdEditUndo(self, e):
			HISTORY_MANAGER.UndoCmd(1)
			
	def __OnCmdEditRedo(self, e):
			HISTORY_MANAGER.DoCmd(1)
	
	def __OnMenuClick(self, e):
			panel = self._panelList.get(e.GetId(), None)
			idx = self._mainNotebook.GetPageIndex(panel)
			if wx.NOT_FOUND == idx:
					self.__AddPanel(panel)
			else:
					self.__RemovePanel(idx)
	
	def __OnMenuUpdateUI(self, e):
			panel = self._panelList.get(e.GetId(), None)
			if wx.NOT_FOUND == self._mainNotebook.GetPageIndex(panel):
					e.Check(False)
			else:
					e.Check(True)
	
	def __OnPanelClose(self, e):
			idx = e.GetSelection()
			self.__RemovePanel(idx)
			e.Veto()
	
	def __CombineAll(self):
			self._auiManager.AddPane(self._mainNotebook, aui.AuiPaneInfo().CenterPane().PaneBorder(False))
			self.__PositionMenuBarAUI(self._auiManager)
			self._auiManager.AddPane(self._toolBarPanel, aui.AuiPaneInfo().ToolbarPane().Top().Row(1).Position(1))
			self._auiManager.AddPane(self._toolBarOperate, aui.AuiPaneInfo().ToolbarPane().Top().Row(1).Position(1))
	
			if GLOBAL_SETTING._visiblePanelList and GLOBAL_SETTING._editorUILayout:
					self._mainNotebook.LoadPerspective(GLOBAL_SETTING._editorUILayout)
	
			self._auiManager.Update()
			self._toolBarPanel.Update()
			self._toolBarOperate.Update()
	
	def __PositionMenuBarAUI(self, fixToolbar = True):
			pn = aui.AuiPaneInfo()
			xx = wx.SystemSettings_GetMetric(wx.SYS_SCREEN_X)
	
			# We add our menu bar as a toolbar, with the following settings
			pn.Name("flat_menu_bar")
			pn.Caption("Menu Bar")
			pn.Top()
			pn.MinSize(wx.Size(xx/2, self._menuBar._barHeight))
			pn.LeftDockable(False)
			pn.RightDockable(False)
			pn.ToolbarPane()
			if not fixToolbar:
					# We add our menu bar as a toolbar, with the following settings
					pn.BestSize(wx.Size(xx, self._menuBar._barHeight))
					pn.FloatingSize(wx.Size(300, self._menuBar._barHeight))
					pn.Floatable(True)
					pn.MaxSize(wx.Size(xx, self._menuBar._barHeight))
					pn.Gripper(True)
	
			else:
					pn.BestSize(wx.Size(xx, self._menuBar._barHeight))
					pn.Gripper(False)
	
			pn.Resizable(False)
			self._auiManager.AddPane(self._menuBar, pn)
	
	def SetFocusToEditorScene(self):
			idx = self._mainNotebook._tabs.GetIdxFromWindow(PANEL_EDITOR_SCENE)
			self._mainNotebook.SetSelection(idx, True)
	
	def __OnClose(self, e):
			wx.GetApp()._keepGoing = False
			GLOBAL_SETTING._editorUILayout = self._mainNotebook.SavePerspective()
			GLOBAL_SETTING._visiblePanelList = set()
			for i in range(0, self._mainNotebook.GetPageCount()):
					GLOBAL_SETTING._visiblePanelList.add(self._mainNotebook.GetPageText(i))
			self._auiManager.UnInit()
			self.Destroy()
			e.Skip()
	
	def __OnWindowResize(self, e):
			if wx.GetApp()._keepGoing:
					WORLD_EDITOR.OnRenderWindowResize(PANEL_EDITOR_SCENE.GetHandle())
	
	def __OnMouseRightDown(self, e):
			self.SetFocusToEditorScene()
			WORLD_EDITOR.OnMouseRightDown(e)
	
	def __OnMouseRightUp(self, e):
			WORLD_EDITOR.OnMouseRightUp(e)
	
	def __OnMouseMiddleDown(self, e):
			self.SetFocusToEditorScene()
			WORLD_EDITOR.OnMouseMiddleDown(e)
	
	def __OnMouseMiddleUp(self, e):
			WORLD_EDITOR.OnMouseMiddleUp(e)
	
	def __OnMouseLeftDown(self, e):
			self.SetFocusToEditorScene()
			WORLD_EDITOR.OnMouseLeftDown(e)
	
	def __OnMouseLeftUp(self, e):
			WORLD_EDITOR.OnMouseLeftUp(e)
	
	def __OnMouseMotion(self, e):
			WORLD_EDITOR.OnMouseMotion(e)
	
	def __OnMouseWheel(self, e):
			WORLD_EDITOR.OnMouseWheel(e)
			
	def __OnKeyDown(self, e):
			WORLD_EDITOR.OnKeyDown(e)
			
	def __OnKeyUp(self, e):
			WORLD_EDITOR.OnKeyUp(e)
			
	def __OnMouseCaptureLost(self, e):
			WORLD_EDITOR.OnMouseCaptureLost(e)        
	
	def __OnCmdFileGlobalSetting(self, e):
			dlg = Dialog.wxDialogGlobalSetting(self)
			dlg.ShowModal()
			dlg.Destroy()